﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================
using System;
using System.Collections.Generic;

namespace Caffeine.Core.Validation
{
    internal abstract class ValidationRule<T>
    {
        #region State

        private readonly Boolean _ignoreCommitted;
        private readonly Boolean _nonDefaultValueRequired;
        private readonly String _valueRequiredMessage;
        private readonly PropertyValidationDel<T> _validationMethod;

        #endregion

        #region Constructors

        public ValidationRule(Boolean nonDefaultValueRequired, String valueRequiredMessage, Boolean ignoreCommitted)
        {
            _nonDefaultValueRequired = nonDefaultValueRequired;
            _valueRequiredMessage = valueRequiredMessage;
            _ignoreCommitted = ignoreCommitted;
            _validationMethod = Validate;
        }

        #endregion

        #region Public

        public Boolean IgnoreCommitted
        {
            get
            {
                return _ignoreCommitted;
            }
        }

        public Boolean NonDefaultValueRequired
        {
            get
            {
                return _nonDefaultValueRequired;
            }
        }

        public String ValueRequiredMessage
        {
            get
            {
                return _valueRequiredMessage;
            }
        }

        public PropertyValidationDel<T> ValidationMethod
        {
            get
            {
                return _validationMethod;
            }
        }
        
        #endregion

        #region Protected

        protected abstract void OnValidate(ModelProperty<T> property, ref IEnumerable<ValidationError> errors, ref Boolean isValid);

        #endregion

        #region Private

        private void Validate(ModelProperty<T> property, ref IEnumerable<ValidationError> errors, ref Boolean isValid)
        {
            isValid = true;

            if (NonDefaultValueRequired && property.IsDefault)
            {
                isValid = false;
                property.Parent.AddError(ref errors, 0, String.IsNullOrWhiteSpace(ValueRequiredMessage) ? ValidationHelper.ValueRequiredErrorMessage : ValueRequiredMessage);
            }
            else
            {
                if (IgnoreCommitted)
                {
                    if (property.IsDirty)
                    {
                        OnValidate(property, ref errors, ref isValid);
                    }
                }
                else
                {
                    OnValidate(property, ref errors, ref isValid);
                }
            }
        }

        #endregion
    }
}
